import { useEffect, useMemo, useRef, useState } from 'react'
import { AlertCircle, Wand2 } from 'lucide-react'
import { useParams } from 'next/navigation'
import {
  Button,
  Popover,
  PopoverAnchor,
  PopoverContent,
  PopoverItem,
  PopoverScrollArea,
  PopoverSection,
} from '@/components/emcn'
import {
  Modal,
  ModalBody,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalTabs,
  ModalTabsContent,
  ModalTabsList,
  ModalTabsTrigger,
} from '@/components/emcn/components/modal/modal'
import { Label } from '@/components/ui/label'
import { cn } from '@/lib/core/utils/cn'
import { createLogger } from '@/lib/logs/console/logger'
import {
  checkEnvVarTrigger,
  EnvVarDropdown,
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/env-var-dropdown'
import {
  checkTagTrigger,
  TagDropdown,
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown'
import { CodeEditor } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/components/code-editor/code-editor'
import { useWand } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-wand'
import {
  useCreateCustomTool,
  useCustomTools,
  useDeleteCustomTool,
  useUpdateCustomTool,
} from '@/hooks/queries/custom-tools'

const logger = createLogger('CustomToolModal')

interface CustomToolModalProps {
  open: boolean
  onOpenChange: (open: boolean) => void
  onSave: (tool: CustomTool) => void
  onDelete?: (toolId: string) => void
  blockId: string
  initialValues?: {
    id?: string
    schema: any
    code: string
  }
}

export interface CustomTool {
  type: 'custom-tool'
  title: string
  name: string
  description: string
  schema: any
  code: string
  params: Record<string, string>
  isExpanded?: boolean
}

type ToolSection = 'schema' | 'code'

export function CustomToolModal({
  open,
  onOpenChange,
  onSave,
  onDelete,
  blockId,
  initialValues,
}: CustomToolModalProps) {
  const params = useParams()
  const workspaceId = params.workspaceId as string
  const [activeSection, setActiveSection] = useState<ToolSection>('schema')
  const [jsonSchema, setJsonSchema] = useState('')
  const [functionCode, setFunctionCode] = useState('')
  const [schemaError, setSchemaError] = useState<string | null>(null)
  const [codeError, setCodeError] = useState<string | null>(null)
  const [isEditing, setIsEditing] = useState(false)
  const [toolId, setToolId] = useState<string | undefined>(undefined)
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
  const [isSchemaPromptActive, setIsSchemaPromptActive] = useState(false)
  const [schemaPromptInput, setSchemaPromptInput] = useState('')
  const [schemaPromptSummary, setSchemaPromptSummary] = useState<string | null>(null)
  const schemaPromptInputRef = useRef<HTMLInputElement | null>(null)

  const [isCodePromptActive, setIsCodePromptActive] = useState(false)
  const [codePromptInput, setCodePromptInput] = useState('')
  const [codePromptSummary, setCodePromptSummary] = useState<string | null>(null)
  const codePromptInputRef = useRef<HTMLInputElement | null>(null)

  const schemaGeneration = useWand({
    wandConfig: {
      enabled: true,
      maintainHistory: true,
      prompt: `You are an expert programmer specializing in creating OpenAI function calling format JSON schemas for custom tools.
Generate ONLY the JSON schema based on the user's request.
The output MUST be a single, valid JSON object, starting with { and ending with }.
The JSON schema MUST follow this specific format:
1. Top-level property "type" must be set to "function"
2. A "function" object containing:
   - "name": A concise, camelCase name for the function
   - "description": A clear description of what the function does
   - "parameters": A JSON Schema object describing the function's parameters with:
     - "type": "object"
     - "properties": An object containing parameter definitions
     - "required": An array of required parameter names

Current schema: {context}

Do not include any explanations, markdown formatting, or other text outside the JSON object.

Valid Schema Examples:

Example 1:
{
  "type": "function",
  "function": {
    "name": "getWeather",
    "description": "Fetches the current weather for a specific location.",
    "parameters": {
      "type": "object",
      "properties": {
        "location": {
          "type": "string",
          "description": "The city and state, e.g., San Francisco, CA"
        },
        "unit": {
          "type": "string",
          "description": "Temperature unit",
          "enum": ["celsius", "fahrenheit"]
        }
      },
      "required": ["location"],
      "additionalProperties": false
    }
  }
}

Example 2:
{
  "type": "function",
  "function": {
    "name": "addItemToOrder",
    "description": "Add one quantity of a food item to the order.",
    "parameters": {
      "type": "object",
      "properties": {
        "itemName": {
          "type": "string",
          "description": "The name of the food item to add to order"
        },
        "quantity": {
          "type": "integer",
          "description": "The quantity of the item to add",
          "default": 1
        }
      },
      "required": ["itemName"],
      "additionalProperties": false
    }
  }
}`,
      placeholder: 'Describe the function parameters and structure...',
      generationType: 'custom-tool-schema',
    },
    currentValue: jsonSchema,
    onGeneratedContent: (content) => {
      setJsonSchema(content)
      setSchemaError(null)
    },
    onStreamChunk: (chunk) => {
      setJsonSchema((prev) => {
        const newSchema = prev + chunk
        if (schemaError) setSchemaError(null)
        return newSchema
      })
    },
  })

  const codeGeneration = useWand({
    wandConfig: {
      enabled: true,
      maintainHistory: true,
      prompt: `You are an expert JavaScript programmer.
Generate ONLY the raw body of a JavaScript function based on the user's request.
The code should be executable within an 'async function(params, environmentVariables) {...}' context.
- 'params' (object): Contains input parameters derived from the JSON schema. Reference these directly by name (e.g., 'userId', 'cityName'). Do NOT use 'params.paramName'.
- 'environmentVariables' (object): Contains environment variables. Reference these using the double curly brace syntax: '{{ENV_VAR_NAME}}'. Do NOT use 'environmentVariables.VAR_NAME' or env.

Current code: {context}

IMPORTANT FORMATTING RULES:
1. Reference Environment Variables: Use the exact syntax {{VARIABLE_NAME}}. Do NOT wrap it in quotes (e.g., use 'const apiKey = {{SERVICE_API_KEY}};' not 'const apiKey = "{{SERVICE_API_KEY}}";'). Our system replaces these placeholders before execution.
2. Reference Input Parameters/Workflow Variables: Reference them directly by name (e.g., 'const city = cityName;' or use directly in template strings like \`\${cityName}\`). Do NOT wrap in quotes or angle brackets.
3. Function Body ONLY: Do NOT include the function signature (e.g., 'async function myFunction() {' or the surrounding '}').
4. Imports: Do NOT include import/require statements unless they are standard Node.js built-in modules (e.g., 'crypto', 'fs'). External libraries are not supported in this context.
5. Output: Ensure the code returns a value if the function is expected to produce output. Use 'return'.
6. Clarity: Write clean, readable code.
7. No Explanations: Do NOT include markdown formatting, comments explaining the rules, or any text other than the raw JavaScript code for the function body.

Example Scenario:
User Prompt: "Fetch weather data from OpenWeather API. Use the city name passed in as 'cityName' and an API Key stored as the 'OPENWEATHER_API_KEY' environment variable."

Generated Code:
const apiKey = {{OPENWEATHER_API_KEY}};
const url = \`https://api.openweathermap.org/data/2.5/weather?q=\${cityName}&appid=\${apiKey}\`;

try {
  const response = await fetch(url, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json'
    }
  });

  if (!response.ok) {
    throw new Error(\`API request failed with status \${response.status}: \${await response.text()}\`);
  }

  const weatherData = await response.json();
  return weatherData;
} catch (error) {
  console.error(\`Error fetching weather data: \${error.message}\`);
  throw error;
}`,
      placeholder: 'Describe the JavaScript function to generate...',
      generationType: 'javascript-function-body',
    },
    currentValue: functionCode,
    onGeneratedContent: (content) => {
      handleFunctionCodeChange(content) // Use existing handler to also trigger dropdown checks
      setCodeError(null) // Clear error on successful generation
    },
    onStreamChunk: (chunk) => {
      setFunctionCode((prev) => {
        const newCode = prev + chunk
        handleFunctionCodeChange(newCode)
        if (codeError) setCodeError(null)
        return newCode
      })
    },
  })

  const [showEnvVars, setShowEnvVars] = useState(false)
  const [showTags, setShowTags] = useState(false)
  const [showSchemaParams, setShowSchemaParams] = useState(false)
  const [searchTerm, setSearchTerm] = useState('')
  const [cursorPosition, setCursorPosition] = useState(0)
  const codeEditorRef = useRef<HTMLDivElement>(null)
  const [activeSourceBlockId, setActiveSourceBlockId] = useState<string | null>(null)
  const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 })
  const [schemaParamSelectedIndex, setSchemaParamSelectedIndex] = useState(0)

  const createToolMutation = useCreateCustomTool()
  const updateToolMutation = useUpdateCustomTool()
  const deleteToolMutation = useDeleteCustomTool()
  const { data: customTools = [] } = useCustomTools(workspaceId)

  useEffect(() => {
    if (!open) return

    if (initialValues) {
      try {
        setJsonSchema(
          typeof initialValues.schema === 'string'
            ? initialValues.schema
            : JSON.stringify(initialValues.schema, null, 2)
        )
        setFunctionCode(initialValues.code || '')
        setIsEditing(true)
        setToolId(initialValues.id)
      } catch (error) {
        logger.error('Error initializing form with initial values:', { error })
        setSchemaError('Failed to load tool data. Please try again.')
      }
    } else {
      resetForm()
    }
  }, [open])

  const resetForm = () => {
    setJsonSchema('')
    setFunctionCode('')
    setSchemaError(null)
    setCodeError(null)
    setActiveSection('schema')
    setIsEditing(false)
    setToolId(undefined)
    setSchemaPromptSummary(null)
    setCodePromptSummary(null)
    setIsSchemaPromptActive(false)
    setIsCodePromptActive(false)
    setSchemaPromptInput('')
    setCodePromptInput('')
    schemaGeneration.closePrompt()
    schemaGeneration.hidePromptInline()
    codeGeneration.closePrompt()
    codeGeneration.hidePromptInline()
  }

  const handleClose = () => {
    if (schemaGeneration.isStreaming) schemaGeneration.cancelGeneration()
    if (codeGeneration.isStreaming) codeGeneration.cancelGeneration()
    resetForm()
    onOpenChange(false)
  }

  const validateJsonSchema = (schema: string): boolean => {
    if (!schema) return false

    try {
      const parsed = JSON.parse(schema)

      if (!parsed.type || parsed.type !== 'function') {
        return false
      }

      if (!parsed.function || !parsed.function.name) {
        return false
      }

      if (!parsed.function.parameters) {
        return false
      }

      if (!parsed.function.parameters.type || parsed.function.parameters.properties === undefined) {
        return false
      }

      return true
    } catch (_error) {
      return false
    }
  }

  /** Extracts parameters from JSON schema for autocomplete */
  const schemaParameters = useMemo(() => {
    try {
      if (!jsonSchema) return []
      const parsed = JSON.parse(jsonSchema)
      const properties = parsed?.function?.parameters?.properties
      if (!properties) return []

      return Object.keys(properties).map((key) => ({
        name: key,
        type: properties[key].type || 'any',
        description: properties[key].description || '',
        required: parsed?.function?.parameters?.required?.includes(key) || false,
      }))
    } catch {
      return []
    }
  }, [jsonSchema])

  /** Memoized schema validation result */
  const isSchemaValid = useMemo(() => validateJsonSchema(jsonSchema), [jsonSchema])

  const handleSave = async () => {
    try {
      if (!jsonSchema) {
        setSchemaError('Schema cannot be empty')
        setActiveSection('schema')
        return
      }

      const parsed = JSON.parse(jsonSchema)

      if (!parsed.type || parsed.type !== 'function') {
        setSchemaError('Schema must have a "type" field set to "function"')
        setActiveSection('schema')
        return
      }

      if (!parsed.function || !parsed.function.name) {
        setSchemaError('Schema must have a "function" object with a "name" field')
        setActiveSection('schema')
        return
      }

      if (!parsed.function.parameters) {
        setSchemaError('Missing function.parameters object')
        setActiveSection('schema')
        return
      }

      if (!parsed.function.parameters.type) {
        setSchemaError('Missing parameters.type field')
        setActiveSection('schema')
        return
      }

      if (parsed.function.parameters.properties === undefined) {
        setSchemaError('Missing parameters.properties field')
        setActiveSection('schema')
        return
      }

      if (
        typeof parsed.function.parameters.properties !== 'object' ||
        parsed.function.parameters.properties === null
      ) {
        setSchemaError('parameters.properties must be an object')
        setActiveSection('schema')
        return
      }

      setSchemaError(null)
      setCodeError(null)

      const schema = JSON.parse(jsonSchema)
      const name = schema.function.name
      const description = schema.function.description || ''

      let toolIdToUpdate: string | undefined = toolId
      if (isEditing && !toolIdToUpdate && initialValues?.schema) {
        const originalName = initialValues.schema.function?.name
        if (originalName) {
          const originalTool = customTools.find(
            (tool) => tool.schema?.function?.name === originalName
          )
          if (originalTool) {
            toolIdToUpdate = originalTool.id
          }
        }
      }

      if (isEditing && toolIdToUpdate) {
        await updateToolMutation.mutateAsync({
          workspaceId,
          toolId: toolIdToUpdate,
          updates: {
            title: name,
            schema,
            code: functionCode || '',
          },
        })
      } else {
        await createToolMutation.mutateAsync({
          workspaceId,
          tool: {
            title: name,
            schema,
            code: functionCode || '',
          },
        })
      }

      const customTool: CustomTool = {
        type: 'custom-tool',
        title: name,
        name,
        description,
        schema,
        code: functionCode || '',
        params: {},
        isExpanded: true,
      }

      onSave(customTool)

      setSchemaPromptSummary(null)
      setCodePromptSummary(null)

      handleClose()
    } catch (error) {
      logger.error('Error saving custom tool:', { error })

      setSchemaPromptSummary(null)
      setCodePromptSummary(null)

      const errorMessage = error instanceof Error ? error.message : 'Failed to save custom tool'

      if (errorMessage.includes('Cannot change function name')) {
        setSchemaError(
          'Function name cannot be changed after creation. To use a different name, delete this tool and create a new one.'
        )
      } else {
        setSchemaError(errorMessage)
      }
      setActiveSection('schema')
    }
  }

  const handleJsonSchemaChange = (value: string) => {
    if (schemaGeneration.isLoading || schemaGeneration.isStreaming) return
    setJsonSchema(value)

    if (value.trim()) {
      try {
        const parsed = JSON.parse(value)

        if (!parsed.type || parsed.type !== 'function') {
          setSchemaError('Missing "type": "function"')
          return
        }

        if (!parsed.function || !parsed.function.name) {
          setSchemaError('Missing function.name field')
          return
        }

        if (!parsed.function.parameters) {
          setSchemaError('Missing function.parameters object')
          return
        }

        if (!parsed.function.parameters.type) {
          setSchemaError('Missing parameters.type field')
          return
        }

        if (parsed.function.parameters.properties === undefined) {
          setSchemaError('Missing parameters.properties field')
          return
        }

        if (
          typeof parsed.function.parameters.properties !== 'object' ||
          parsed.function.parameters.properties === null
        ) {
          setSchemaError('parameters.properties must be an object')
          return
        }

        setSchemaError(null)
      } catch {
        setSchemaError('Invalid JSON format')
      }
    } else {
      setSchemaError(null)
    }
  }

  const handleFunctionCodeChange = (value: string) => {
    if (codeGeneration.isLoading || codeGeneration.isStreaming) {
      setFunctionCode(value)
      if (codeError) {
        setCodeError(null)
      }
      return
    }

    setFunctionCode(value)
    if (codeError) {
      setCodeError(null)
    }

    const textarea = codeEditorRef.current?.querySelector('textarea')
    if (textarea) {
      const pos = textarea.selectionStart
      setCursorPosition(pos)

      const textBeforeCursor = value.substring(0, pos)
      const lines = textBeforeCursor.split('\n')
      const currentLine = lines.length
      const currentCol = lines[lines.length - 1].length

      try {
        if (codeEditorRef.current) {
          const editorRect = codeEditorRef.current.getBoundingClientRect()
          const lineHeight = 21

          const top = currentLine * lineHeight + 5
          const left = Math.min(currentCol * 8, editorRect.width - 260)

          setDropdownPosition({ top, left })
        }
      } catch (error) {
        logger.error('Error calculating cursor position:', { error })
      }

      const envVarTrigger = checkEnvVarTrigger(value, pos)
      setShowEnvVars(envVarTrigger.show && !codeGeneration.isStreaming)
      setSearchTerm(envVarTrigger.show ? envVarTrigger.searchTerm : '')

      const tagTrigger = checkTagTrigger(value, pos)
      setShowTags(tagTrigger.show && !codeGeneration.isStreaming)
      if (!tagTrigger.show) {
        setActiveSourceBlockId(null)
      }

      if (!codeGeneration.isStreaming && schemaParameters.length > 0) {
        const schemaParamTrigger = checkSchemaParamTrigger(value, pos, schemaParameters)
        if (schemaParamTrigger.show && !showSchemaParams) {
          setShowSchemaParams(true)
          setSchemaParamSelectedIndex(0)
        } else if (!schemaParamTrigger.show && showSchemaParams) {
          setShowSchemaParams(false)
        }
      }
    }
  }

  const checkSchemaParamTrigger = (text: string, cursorPos: number, parameters: any[]) => {
    if (parameters.length === 0) return { show: false, searchTerm: '' }

    const beforeCursor = text.substring(0, cursorPos)
    const words = beforeCursor.split(/[\s=();,{}[\]]+/)
    const currentWord = words[words.length - 1] || ''

    if (currentWord.length > 0 && /^[a-zA-Z_][\w]*$/.test(currentWord)) {
      const matchingParams = parameters.filter((param) =>
        param.name.toLowerCase().startsWith(currentWord.toLowerCase())
      )
      return { show: matchingParams.length > 0, searchTerm: currentWord, matches: matchingParams }
    }

    return { show: false, searchTerm: '' }
  }

  const handleEnvVarSelect = (newValue: string) => {
    setFunctionCode(newValue)
    setShowEnvVars(false)
  }

  const handleTagSelect = (newValue: string) => {
    setFunctionCode(newValue)
    setShowTags(false)
    setActiveSourceBlockId(null)
  }

  const handleSchemaParamSelect = (paramName: string) => {
    const textarea = codeEditorRef.current?.querySelector('textarea')
    if (textarea) {
      const pos = textarea.selectionStart
      const beforeCursor = functionCode.substring(0, pos)
      const afterCursor = functionCode.substring(pos)

      const words = beforeCursor.split(/[\s=();,{}[\]]+/)
      const currentWord = words[words.length - 1] || ''
      const wordStart = beforeCursor.lastIndexOf(currentWord)

      const newValue = beforeCursor.substring(0, wordStart) + paramName + afterCursor
      setFunctionCode(newValue)
      setShowSchemaParams(false)

      setTimeout(() => {
        textarea.focus()
        textarea.setSelectionRange(wordStart + paramName.length, wordStart + paramName.length)
      }, 0)
    }
  }

  const handleKeyDown = (e: React.KeyboardEvent) => {
    const isSchemaPromptVisible = activeSection === 'schema' && schemaGeneration.isPromptVisible
    const isCodePromptVisible = activeSection === 'code' && codeGeneration.isPromptVisible

    if (e.key === 'Escape') {
      if (isSchemaPromptVisible) {
        schemaGeneration.hidePromptInline()
        e.preventDefault()
        e.stopPropagation()
        return
      }
      if (isCodePromptVisible) {
        codeGeneration.hidePromptInline()
        e.preventDefault()
        e.stopPropagation()
        return
      }
      if (showEnvVars || showTags || showSchemaParams) {
        setShowEnvVars(false)
        setShowTags(false)
        setShowSchemaParams(false)
        e.preventDefault()
        e.stopPropagation()
        return
      }
    }

    if (activeSection === 'schema' && schemaGeneration.isStreaming) {
      e.preventDefault()
      return
    }
    if (activeSection === 'code' && codeGeneration.isStreaming) {
      e.preventDefault()
      return
    }

    if (showSchemaParams && schemaParameters.length > 0) {
      switch (e.key) {
        case 'ArrowDown':
          e.preventDefault()
          e.stopPropagation()
          setSchemaParamSelectedIndex((prev) => Math.min(prev + 1, schemaParameters.length - 1))
          break
        case 'ArrowUp':
          e.preventDefault()
          e.stopPropagation()
          setSchemaParamSelectedIndex((prev) => Math.max(prev - 1, 0))
          break
        case 'Enter':
          e.preventDefault()
          e.stopPropagation()
          if (schemaParamSelectedIndex >= 0 && schemaParamSelectedIndex < schemaParameters.length) {
            const selectedParam = schemaParameters[schemaParamSelectedIndex]
            handleSchemaParamSelect(selectedParam.name)
          }
          break
        case 'Escape':
          e.preventDefault()
          e.stopPropagation()
          setShowSchemaParams(false)
          break
      }
      return
    }

    if (showEnvVars || showTags) {
      if (['ArrowDown', 'ArrowUp', 'Enter'].includes(e.key)) {
        e.preventDefault()
        e.stopPropagation()
      }
    }
  }

  const handleSchemaWandClick = () => {
    if (schemaGeneration.isLoading || schemaGeneration.isStreaming) return
    setIsSchemaPromptActive(true)
    setSchemaPromptInput(schemaPromptSummary ?? '')
    setTimeout(() => {
      schemaPromptInputRef.current?.focus()
    }, 0)
  }

  const handleSchemaPromptBlur = () => {
    if (!schemaPromptInput.trim() && !schemaGeneration.isStreaming) {
      setIsSchemaPromptActive(false)
    }
  }

  const handleSchemaPromptChange = (value: string) => {
    setSchemaPromptInput(value)
  }

  const handleSchemaPromptSubmit = () => {
    const trimmedPrompt = schemaPromptInput.trim()
    if (!trimmedPrompt || schemaGeneration.isLoading || schemaGeneration.isStreaming) return
    setSchemaPromptSummary(trimmedPrompt)
    schemaGeneration.generateStream({ prompt: trimmedPrompt })
    setSchemaPromptInput('')
    setIsSchemaPromptActive(false)
  }

  const handleSchemaPromptKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      e.preventDefault()
      handleSchemaPromptSubmit()
    } else if (e.key === 'Escape') {
      e.preventDefault()
      setSchemaPromptInput('')
      setIsSchemaPromptActive(false)
    }
  }

  const handleCodeWandClick = () => {
    if (codeGeneration.isLoading || codeGeneration.isStreaming) return
    setIsCodePromptActive(true)
    setCodePromptInput(codePromptSummary ?? '')
    setTimeout(() => {
      codePromptInputRef.current?.focus()
    }, 0)
  }

  const handleCodePromptBlur = () => {
    if (!codePromptInput.trim() && !codeGeneration.isStreaming) {
      setIsCodePromptActive(false)
    }
  }

  const handleCodePromptChange = (value: string) => {
    setCodePromptInput(value)
  }

  const handleCodePromptSubmit = () => {
    const trimmedPrompt = codePromptInput.trim()
    if (!trimmedPrompt || codeGeneration.isLoading || codeGeneration.isStreaming) return
    setCodePromptSummary(trimmedPrompt)
    codeGeneration.generateStream({ prompt: trimmedPrompt })
    setCodePromptInput('')
    setIsCodePromptActive(false)
  }

  const handleCodePromptKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      e.preventDefault()
      handleCodePromptSubmit()
    } else if (e.key === 'Escape') {
      e.preventDefault()
      setCodePromptInput('')
      setIsCodePromptActive(false)
    }
  }

  const handleDelete = async () => {
    if (!toolId || !isEditing) return

    try {
      setShowDeleteConfirm(false)

      await deleteToolMutation.mutateAsync({
        workspaceId,
        toolId,
      })
      logger.info(`Deleted tool: ${toolId}`)

      if (onDelete) {
        onDelete(toolId)
      }

      handleClose()
    } catch (error) {
      logger.error('Error deleting custom tool:', error)
      const errorMessage = error instanceof Error ? error.message : 'Failed to delete custom tool'
      setSchemaError(`${errorMessage}. Please try again.`)
      setActiveSection('schema')
      setShowDeleteConfirm(false)
    }
  }

  return (
    <>
      <Modal open={open} onOpenChange={handleClose}>
        <ModalContent
          className='h-[80vh] w-[900px]'
          onKeyDown={(e) => {
            if (e.key === 'Escape' && (showEnvVars || showTags || showSchemaParams)) {
              e.preventDefault()
              e.stopPropagation()
              setShowEnvVars(false)
              setShowTags(false)
              setShowSchemaParams(false)
            }
          }}
        >
          <ModalHeader>{isEditing ? 'Edit Agent Tool' : 'Create Agent Tool'}</ModalHeader>

          <ModalTabs
            value={activeSection}
            onValueChange={(value) => setActiveSection(value as ToolSection)}
            className='flex min-h-0 flex-1 flex-col'
          >
            <ModalTabsList activeValue={activeSection}>
              <ModalTabsTrigger value='schema'>Schema</ModalTabsTrigger>
              <ModalTabsTrigger value='code'>Code</ModalTabsTrigger>
            </ModalTabsList>

            <ModalBody className='min-h-0 flex-1'>
              <ModalTabsContent value='schema'>
                <div className='mb-1 flex min-h-6 items-center justify-between gap-2'>
                  <div className='flex min-w-0 items-center gap-2'>
                    <Label htmlFor='json-schema' className='font-medium text-[13px]'>
                      JSON Schema
                    </Label>
                    {schemaError && (
                      <div className='ml-2 flex min-w-0 items-center gap-1 text-[var(--text-error)] text-xs'>
                        <AlertCircle className='h-3 w-3 flex-shrink-0' />
                        <span className='truncate'>{schemaError}</span>
                      </div>
                    )}
                  </div>
                  <div className='flex min-w-0 flex-1 items-center justify-end gap-1 pr-[4px]'>
                    {!isSchemaPromptActive && schemaPromptSummary && (
                      <span className='text-[var(--text-tertiary)] text-xs italic'>
                        with {schemaPromptSummary}
                      </span>
                    )}
                    {!isSchemaPromptActive ? (
                      <button
                        type='button'
                        onClick={handleSchemaWandClick}
                        disabled={schemaGeneration.isLoading || schemaGeneration.isStreaming}
                        className='inline-flex h-[16px] w-[16px] items-center justify-center rounded-full hover:bg-transparent disabled:opacity-50'
                        aria-label='Generate schema with AI'
                      >
                        <Wand2 className='!h-[12px] !w-[12px] text-[var(--text-secondary)]' />
                      </button>
                    ) : (
                      <input
                        ref={schemaPromptInputRef}
                        type='text'
                        value={schemaGeneration.isStreaming ? 'Generating...' : schemaPromptInput}
                        onChange={(e) => handleSchemaPromptChange(e.target.value)}
                        onBlur={handleSchemaPromptBlur}
                        onKeyDown={handleSchemaPromptKeyDown}
                        disabled={schemaGeneration.isStreaming}
                        className='h-[16px] w-full border-none bg-transparent py-0 pr-[2px] text-right font-medium text-[12px] text-[var(--text-primary)] leading-[14px] placeholder:text-[var(--text-muted)] focus:outline-none'
                        placeholder='Describe schema...'
                      />
                    )}
                  </div>
                </div>
                <CodeEditor
                  value={jsonSchema}
                  onChange={handleJsonSchemaChange}
                  language='json'
                  showWandButton={false}
                  placeholder={`{
  "type": "function",
  "function": {
    "name": "addItemToOrder",
    "description": "Add one quantity of a food item to the order.",
    "parameters": {
      "type": "object",
      "properties": {
        "itemName": {
          "type": "string",
          "description": "The name of the food item to add to order"
        }
      },
      "required": ["itemName"]
    }
  }
}`}
                  minHeight='420px'
                  className={cn(
                    'bg-[var(--bg)]',
                    schemaError && 'border-[var(--text-error)]',
                    (schemaGeneration.isLoading || schemaGeneration.isStreaming) &&
                      'cursor-not-allowed opacity-50'
                  )}
                  gutterClassName='bg-[var(--bg)]'
                  disabled={schemaGeneration.isLoading || schemaGeneration.isStreaming}
                  onKeyDown={handleKeyDown}
                />
              </ModalTabsContent>

              <ModalTabsContent value='code'>
                <div className='mb-1 flex min-h-6 items-center justify-between gap-2'>
                  <div className='flex min-w-0 items-center gap-2'>
                    <Label htmlFor='function-code' className='font-medium text-[13px]'>
                      Code
                    </Label>
                    {codeError && !codeGeneration.isStreaming && (
                      <div className='ml-2 flex min-w-0 items-center gap-1 text-[var(--text-error)] text-xs'>
                        <AlertCircle className='h-3 w-3 flex-shrink-0' />
                        <span className='truncate'>{codeError}</span>
                      </div>
                    )}
                  </div>
                  <div className='flex min-w-0 flex-1 items-center justify-end gap-1 pr-[4px]'>
                    {!isCodePromptActive && codePromptSummary && (
                      <span className='text-[var(--text-tertiary)] text-xs italic'>
                        with {codePromptSummary}
                      </span>
                    )}
                    {!isCodePromptActive ? (
                      <button
                        type='button'
                        onClick={handleCodeWandClick}
                        disabled={codeGeneration.isLoading || codeGeneration.isStreaming}
                        className='inline-flex h-[16px] w-[16px] items-center justify-center rounded-full hover:bg-transparent disabled:opacity-50'
                        aria-label='Generate code with AI'
                      >
                        <Wand2 className='!h-[12px] !w-[12px] text-[var(--text-secondary)]' />
                      </button>
                    ) : (
                      <input
                        ref={codePromptInputRef}
                        type='text'
                        value={codeGeneration.isStreaming ? 'Generating...' : codePromptInput}
                        onChange={(e) => handleCodePromptChange(e.target.value)}
                        onBlur={handleCodePromptBlur}
                        onKeyDown={handleCodePromptKeyDown}
                        disabled={codeGeneration.isStreaming}
                        className='h-[16px] w-full border-none bg-transparent py-0 pr-[2px] text-right font-medium text-[12px] text-[var(--text-primary)] leading-[14px] placeholder:text-[var(--text-muted)] focus:outline-none'
                        placeholder='Describe code...'
                      />
                    )}
                  </div>
                </div>
                {schemaParameters.length > 0 && (
                  <div className='mb-2 rounded-[6px] border bg-[var(--surface-2)] p-2'>
                    <p className='text-[var(--text-tertiary)] text-xs'>
                      <span className='font-medium'>Available parameters:</span>{' '}
                      {schemaParameters.map((param, index) => (
                        <span key={param.name}>
                          <code className='rounded bg-[var(--bg)] px-1 py-0.5 text-[var(--text-primary)]'>
                            {param.name}
                          </code>
                          {index < schemaParameters.length - 1 && ', '}
                        </span>
                      ))}
                      {'. '}Start typing a parameter name for autocomplete.
                    </p>
                  </div>
                )}
                <div ref={codeEditorRef} className='relative'>
                  <CodeEditor
                    value={functionCode}
                    onChange={handleFunctionCodeChange}
                    language='javascript'
                    showWandButton={false}
                    placeholder={'return schemaVariable + {{environmentVariable}}'}
                    minHeight={schemaParameters.length > 0 ? '380px' : '420px'}
                    className={cn(
                      'bg-[var(--bg)]',
                      codeError && !codeGeneration.isStreaming && 'border-[var(--text-error)]',
                      (codeGeneration.isLoading || codeGeneration.isStreaming) &&
                        'cursor-not-allowed opacity-50'
                    )}
                    gutterClassName='bg-[var(--bg)]'
                    highlightVariables={true}
                    disabled={codeGeneration.isLoading || codeGeneration.isStreaming}
                    onKeyDown={handleKeyDown}
                    schemaParameters={schemaParameters}
                  />

                  {showEnvVars && (
                    <EnvVarDropdown
                      visible={showEnvVars}
                      onSelect={handleEnvVarSelect}
                      searchTerm={searchTerm}
                      inputValue={functionCode}
                      cursorPosition={cursorPosition}
                      workspaceId={workspaceId}
                      onClose={() => {
                        setShowEnvVars(false)
                        setSearchTerm('')
                      }}
                      className='w-64'
                      style={{
                        position: 'absolute',
                        top: `${dropdownPosition.top}px`,
                        left: `${dropdownPosition.left}px`,
                      }}
                    />
                  )}

                  {showTags && (
                    <TagDropdown
                      visible={showTags}
                      onSelect={handleTagSelect}
                      blockId={blockId}
                      activeSourceBlockId={activeSourceBlockId}
                      inputValue={functionCode}
                      cursorPosition={cursorPosition}
                      onClose={() => {
                        setShowTags(false)
                        setActiveSourceBlockId(null)
                      }}
                      className='w-64'
                      style={{
                        position: 'absolute',
                        top: `${dropdownPosition.top}px`,
                        left: `${dropdownPosition.left}px`,
                      }}
                    />
                  )}

                  {showSchemaParams && schemaParameters.length > 0 && (
                    <Popover
                      open={showSchemaParams}
                      onOpenChange={(open) => {
                        if (!open) {
                          setShowSchemaParams(false)
                        }
                      }}
                    >
                      <PopoverAnchor asChild>
                        <div
                          className='pointer-events-none'
                          style={{
                            position: 'absolute',
                            top: `${dropdownPosition.top}px`,
                            left: `${dropdownPosition.left}px`,
                            width: '1px',
                            height: '1px',
                          }}
                        />
                      </PopoverAnchor>
                      <PopoverContent
                        maxHeight={240}
                        className='min-w-[260px] max-w-[260px]'
                        side='bottom'
                        align='start'
                        collisionPadding={6}
                        onOpenAutoFocus={(e) => e.preventDefault()}
                        onCloseAutoFocus={(e) => e.preventDefault()}
                      >
                        <PopoverScrollArea>
                          <PopoverSection>Available Parameters</PopoverSection>
                          {schemaParameters.map((param, index) => (
                            <PopoverItem
                              key={param.name}
                              rootOnly
                              active={index === schemaParamSelectedIndex}
                              onMouseEnter={() => setSchemaParamSelectedIndex(index)}
                              onMouseDown={(e) => {
                                e.preventDefault()
                                e.stopPropagation()
                                handleSchemaParamSelect(param.name)
                              }}
                              className='flex items-center gap-2'
                            >
                              <div
                                className='flex h-5 w-5 items-center justify-center rounded'
                                style={{ backgroundColor: '#2F8BFF' }}
                              >
                                <span className='h-3 w-3 font-bold text-white text-xs'>P</span>
                              </div>
                              <span className='flex-1 truncate'>{param.name}</span>
                              <span className='text-[var(--text-tertiary)] text-xs'>
                                {param.type}
                              </span>
                            </PopoverItem>
                          ))}
                        </PopoverScrollArea>
                      </PopoverContent>
                    </Popover>
                  )}
                </div>
              </ModalTabsContent>
            </ModalBody>
          </ModalTabs>

          {activeSection === 'schema' && (
            <ModalFooter className='items-center justify-between'>
              {isEditing ? (
                <Button
                  variant='default'
                  onClick={() => setShowDeleteConfirm(true)}
                  className='bg-[var(--text-error)] text-white hover:bg-[var(--text-error)]'
                >
                  Delete
                </Button>
              ) : (
                <div />
              )}
              <div className='flex gap-2'>
                <Button variant='default' onClick={handleClose}>
                  Cancel
                </Button>
                <Button
                  variant='primary'
                  onClick={() => setActiveSection('code')}
                  disabled={!isSchemaValid || !!schemaError}
                >
                  Next
                </Button>
              </div>
            </ModalFooter>
          )}

          {activeSection === 'code' && (
            <ModalFooter className='items-center justify-between'>
              {isEditing ? (
                <Button
                  variant='default'
                  onClick={() => setShowDeleteConfirm(true)}
                  className='bg-[var(--text-error)] text-white hover:bg-[var(--text-error)]'
                >
                  Delete
                </Button>
              ) : (
                <Button variant='default' onClick={() => setActiveSection('schema')}>
                  Back
                </Button>
              )}
              <div className='flex gap-2'>
                <Button variant='default' onClick={handleClose}>
                  Cancel
                </Button>
                <Button
                  variant='primary'
                  onClick={handleSave}
                  disabled={!isSchemaValid || !!schemaError}
                >
                  {isEditing ? 'Update Tool' : 'Save Tool'}
                </Button>
              </div>
            </ModalFooter>
          )}
        </ModalContent>
      </Modal>

      <Modal open={showDeleteConfirm} onOpenChange={setShowDeleteConfirm}>
        <ModalContent className='w-[400px]'>
          <ModalHeader>Delete Custom Tool</ModalHeader>
          <ModalBody>
            <p className='text-[12px] text-[var(--text-tertiary)]'>
              This will permanently delete the tool and remove it from any workflows that are using
              it. <span className='text-[var(--text-error)]'>This action cannot be undone.</span>
            </p>
          </ModalBody>
          <ModalFooter>
            <Button
              variant='default'
              onClick={() => setShowDeleteConfirm(false)}
              disabled={deleteToolMutation.isPending}
            >
              Cancel
            </Button>
            <Button
              variant='primary'
              onClick={handleDelete}
              disabled={deleteToolMutation.isPending}
              className='!bg-[var(--text-error)] !text-white hover:!bg-[var(--text-error)]/90'
            >
              {deleteToolMutation.isPending ? 'Deleting...' : 'Delete'}
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </>
  )
}
